<?php
/**
 * Created by PhpStorm.
 * User: shutao
 * Date: 2019-01-11
 * Time: 10:33
 */

namespace wechat\help;

use tt\common\help\ModelHelper;
use ttcommon\base\Data;
use ttext\backend\admin\services\UserService;
use wechat\hook\AuthHook;
use wechat\models\WeUser;
use wechat\models\WeUserOpenid;
use wechat\services\WeConfigService;

/*
 * 使用示例
if (!$config = WeiXinService::weConfigFromAppid(self::APPID)) {
    throw new \Exception('找不到指定公众号');
}

$app = WeiXinService::app($config);
$wos = new WechatOpenidScanHelp($app);
$wosDb = new WechatOpenidDbHelp($wos);
foreach ($wos as $key => $appid) { // 请求端口每天限额 500 次
    if ($wosDb->currentUserOpenidExists()) {
        continue; // 最近的已经关注过
    } else {
        // 如果需要，可以在这里开启事务
        $we_id = $wosDb->createUserInfo();
        $wosDb->createUserOpenid($we_id);
        // 事务结束
    }
    if ($wos->request_count > 1) { // 第2页了
        break;
    }
}
pr('完成');
*/

/**
 * WechatOpenidScanHelp 类负责不断地读取 openid，
 * 而此类的主要作用是：检查 openid 是否在 we_user_openid 记录中；如果不存在，则登记；
 */
class WechatOpenidDbHelp
{
    /**
     * @var WechatOpenidScanHelp
     */
    private $_woHelp;
    private $_config;

    /**
     * WechatOpenidDbHelp constructor.
     * @param WechatOpenidScanHelp $woHelp
     */
    public function __construct($woHelp)
    {
        $this->_woHelp = $woHelp;
        $this->_config = $woHelp->app->getConfig();
        $this->_config['type'] = WeConfigService::typeFromAppid($this->_config['app_id']);
    }

    /**
     * 检查是否已经登记过（会按时间从近到远取出记录检查）
     * @return bool
     */
    public function currentUserOpenidExists()
    {
        return WeUserOpenid::find()->where([
            'openid' => $this->_config['app_id'],
            'user_openid' => $this->_woHelp->current()
        ])->exists();
    }

    /**
     * @return integer 在 we_user 中的 id
     * @throws
     */
    public function createUserInfo()
    {
        // https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140839
        $original = $this->_woHelp->userInfo();
        // 将返回的数据记录到 we_user 中
        Data::hasSet($original, 'unionid');
        if ($record = WeUser::find()->where(['weixin_unionid' => $original['unionid']])
            ->select('id')->asArray()->one()) {
            return $record['id'];
        }

        $uid = AuthHook::$createUserWhenFirstSubscribe
            ? $user = UserService::registerWithUuid($original['unionid'])
            : 0;

        $weUser = new WeUser();
        $weUser->nickname = $original['nickname'];
        $weUser->sex = (int)$original['sex'];
        $weUser->city = $original['city'];
        $weUser->province = $original['province'];
        $weUser->country = $original['country'];
        $weUser->avatar = $original['headimgurl'];
        $weUser->weixin_unionid = $original['unionid'];
        $weUser->uid = $uid;
        if ($weUser->insert() === false) {
            throw new \Exception(ModelHelper::errorMessages($weUser));
        }
        return $weUser->id;
    }

    /**
     * @param integer $we_id self::createUserInfo() 中的返回值，we_user 的记录 id
     * @param bool $checkExists 是否检查
     * @throws
     */
    public function createUserOpenid($we_id, $checkExists = false)
    {
        if ($checkExists) {
            if ($this->currentUserOpenidExists()) {
                return;
            }
        }
        $weUserOpenid = new WeUserOpenid();
        $weUserOpenid->we_id = $we_id;
        $weUserOpenid->openid = $this->_config['app_id'];
        $weUserOpenid->user_openid = $this->_woHelp->current();
        $weUserOpenid->type = $this->_config['type'];
        if ($weUserOpenid->insert() === false) {
            throw new \Exception(ModelHelper::errorMessages($weUserOpenid));
        }
    }

    /**
     * 更新，好像用不到
     * @param integer $we_id
     * @throws \yii\db\Exception
     * @deprecated
     */
    public function updateUserOpenid($we_id)
    {
        \Yii::$app->db->createCommand()->update(
            WeUserOpenid::tableName(), ['we_id' => $we_id],
            [
                'type' => $this->_config['type'],
                'openid' => $this->_config['app_id'],
                'user_openid' => $this->_woHelp->current()
            ]
        )->execute();
    }

    /**
     * 一次性全部将 openid 都导入到数据表中
     * @deprecated 危险，因为不清楚是否有重复记录
     * @throws \Exception
     */
//    public function batchUserOpenids()
//    {
//        $batch = [];
//        foreach ($this->_woHelp->getOpenids() as $openid) {
//            $batch[] = [
//                'type' => $this->_config['type'],
//                'openid' => $this->_config['app_id'],
//                'user_openid' => $openid
//            ];
//        }
//        WeUserOpenid::batchSave($batch);
//    }
}